import csv
from pprint import pprint
from case_convert import kebab_case, pascal_case
from collections import namedtuple

Demo = namedtuple("Demo", "cat comp comp_name demo_name demo")


def named_row(row):
    return Demo(*row)


def save_file(file, items):
    with open(file, mode="w", encoding="utf-8") as f:
        for item in items:
            f.write(item)
            f.write("\n")


def component_kebab(name: str):
    if name == "QRCode":
        return "qr-code"
    if name == "Autocomplete":
        return "auto-complete"
    return kebab_case(name)


def component_module_pascal(name: str):
    if name == "Breadcrumb":
        return "BreadCrumb"
    if name == "Dropdown":
        return "DropDown"
    if name == "QRCode":
        return "QRCode"
    if name == "Tooltip":
        return "ToolTip"
    return pascal_case(name)


def component_pascal(name: str):
    kebab = component_kebab(name)
    return pascal_case(kebab)


def get_nz_module_name(component_name):
    """Button -> NzButtonModule"""
    pascal = component_module_pascal(component_name)
    return f"Nz{pascal}Module"


def get_import_statement(component_name):
    """Button -> import { NzButtonModule } from 'ng-zorro-antd/button';"""
    component_kebab = component_kebab(component_name)
    nz_module_name = get_nz_module_name(component_name)
    return f"import {{ {nz_module_name} }} from 'ng-zorro-antd/{component_kebab}';"


def get_demo_full_kebab(demo, comp):
    comp_kebab = component_kebab(comp)
    return f"{comp_kebab}-{kebab_case(demo)}-demo"


def get_route_path(demo, comp):
    """
    demo: basic
    comp: QRCode
    'qr-code-basic'
    """
    return f"{component_kebab(comp)}-{kebab_case(demo)}"


def get_demo_comp(demo, comp):
    """
    demo: basic
    comp: QRCode
    QrCodeBasicDemoComponent
    """
    return f"{component_pascal(comp)}{pascal_case(demo)}DemoComponent"


def get_demo_comp_pascal(demo: Demo) -> str:
    """
    demo: basic
    comp: QRCode
    QrCodeBasicDemoComponent
    """
    return f"{component_pascal(demo.comp)}{pascal_case(demo.demo)}DemoComponent"


def get_demo_comp_imp(demo: Demo) -> str:
    """

    Args:
        demo (Demo): _description_

    Returns:
        import { QrCodeBasicDemoComponent } from './qr-code/qr-code-basic-demo/qr-code-basic-demo.component';
    """
    return f"import {{ {get_demo_comp_pascal(demo)} }} from './{component_kebab(demo.comp)}/{get_demo_full_kebab(demo.demo, demo.comp)}/{get_demo_full_kebab(demo.demo, demo.comp)}.component';"


def get_route_setting(demo, comp):
    """
    demo: basic
    comp: QRCode
    { path: 'qr-code-basic', component: QrBasicDemoComponent },
    """
    return f"{{ path: '{get_route_path(demo, comp)}', component: {get_demo_comp(demo, comp)} }},"


def iter_routes():
    for row in iter_rows():
        demo = row[4]
        comp = row[1]
        yield get_route_setting(demo, comp)


def iter_lines():
    with open(r"doc\demos.csv", encoding="utf-8") as f:
        for line in f:
            if line.strip() != "":
                yield line


def iter_rows():
    csv_reader = csv.reader(iter_lines())
    for row in csv_reader:
        yield row


def iter_demos():
    csv_reader = csv.reader(iter_lines())
    for row in csv_reader:
        yield named_row(row)


def iter_components():
    rows = iter_rows()
    components = set()
    for row in rows:
        component = row[1]
        if not component in components:
            components.add(component)
            yield component


def iter_comps():
    demos = iter_demos()
    components = set()
    for demo in demos:
        component = demo.comp
        if not component in components:
            components.add(component)
            yield (demo.comp, demo.comp_name)


def indent(n):
    return " " * n


def iter_cat():
    cats = set()
    for demo in iter_demos():
        if not demo.cat in cats:
            cats.add(demo.cat)
            yield demo.cat


def iter_comp_by_cat(cat: str):
    comps = set()
    for demo in iter_demos():
        if demo.cat != cat:
            continue
        if not demo.comp in comps:
            comps.add(demo.comp)
            yield (demo.comp, demo.comp_name)


def iter_demo_by_comp(comp: str):
    for demo in iter_demos():
        if demo.comp != comp:
            continue
        yield demo


def iter_menu():
    for cat in iter_cat():
        yield f'<li nz-submenu nzTitle="{cat}" nzIcon="dashboard">'
        yield "  <ul>"
        for comp, comp_name in iter_comp_by_cat(cat):
            yield indent(4) + f'<li nz-submenu nzTitle="{comp_name}">'
            yield indent(4) + "  <ul>"

            for demo in iter_demo_by_comp(comp):
                yield indent(8) + "<li nz-menu-item nzMatchRouter>"
                yield indent(8) + (
                    f'  <a routerLink="/{get_route_path(demo.demo, demo.comp)}">{demo.demo_name}</a>'
                )
                yield indent(8) + "</li>"
            yield indent(4) + "  </ul>"
            yield indent(4) + "</li>"
        yield "  </ul>"
        yield "</li>"


def iter_compoent_md():
    for cat in iter_cat():
        yield f"# {cat}"
        for comp, comp_name in iter_comp_by_cat(cat):
            yield f"## {comp} {comp_name}"


def ng_c(demo, comp):
    comp_kebab = component_kebab(comp)
    demo_full_kebab = get_demo_full_kebab(demo, comp)
    return f"ng g c {comp_kebab}/{demo_full_kebab} --module=app"


# save_file(r"doc/imports.txt", [get_import_statement(comp) for comp in iter_components()])
# save_file(r"doc/modules.txt", [get_nz_module_name(comp) + "," for comp in iter_components()])
# save_file(r"tools/New-Components.ps1", [ng_c(row[4], row[1]) for row in iter_rows()])
# save_file(r"doc/routes.txt", iter_routes())
# save_file(r"doc/demo-components.txt", iter_routes())
# save_file(r"doc/demo-components-imports.txt", [get_demo_comp_imp(demo) for demo in iter_demos()])
# save_file(r"doc/nav-menu.txt", iter_menu())
# save_file(r"doc/components.md", iter_compoent_md())
save_file(
    r"doc/components-todo.md", [f"- [ ] {comp[0]} {comp[1]}" for comp in iter_comps()]
)
